package com.spzx.auth.service;

import com.spzx.auth.form.LoginBody;
import com.spzx.auth.form.RegisterBody;
import com.spzx.common.core.constant.Constants;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.utils.ip.IpUtils;
import com.spzx.common.security.utils.SecurityUtils;
import com.spzx.system.api.model.LoginUser;
import com.spzx.user.api.domain.UpdateUserLogin;
import com.spzx.user.api.domain.UserInfo;
import com.spzx.user.api.model.RemoteUserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Date;


/**
 * @Author ChenXing
 * @Description 虽然有些奇怪，但还是跟着课件
 * @Create 2024/8/12 18:06
 */

@Component
public class H5LoginService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private SysRecordLogService sysRecordLogService;

    @Autowired
    private RemoteUserInfoService remoteUserInfoService;

    @Autowired
    private SysPasswordService sysPasswordService;

    public void register(RegisterBody registerBody) {
        // 实际工作中，这里不该得到 用户的密码明文，有点违法的嫌疑
        // 这里拿到的是前端传过来的数据，前端的加密方式应该和后端要保持一致
        String password = registerBody.getPassword();
        String registerCode = registerBody.getCode(); // 短信验证码
        String nickName = registerBody.getNickName();
        String username = registerBody.getUsername();

        // 判空，同时，实际工作中校验数据的判断 不能使用 if 只能写逻辑分支的时候 用 if
        // spring 框架提供的断言工具类 Assert，自己也可以去改写自己的断言
        // 如果 password 变量只包含空格，没有实际的文本内容 StringUtils.hasText(password) 将返回 false。如果 password 变量包含至少一个非空白字符，那么 hasText 方法将返回 true。

        //  Assert.isTrue(StringUtils.hasText(password)&&StringUtils.hasText(registerCode)&&StringUtils.hasText(nickName)&&StringUtils.hasText(username),"用户名或密码或昵称或验证码 不能为空");

        Assert.isTrue(StringUtils.hasText(password),"密码不能为空");
        Assert.isTrue(StringUtils.hasText(registerCode),"验证码不能为空");
        Assert.isTrue(StringUtils.hasText(nickName),"昵称不能为空");
        Assert.isTrue(StringUtils.hasText(username),"用户名不能为空");

        // 判断 输入的验证码 和 redis 保存中的验证码是否一致
        String cacheCode = stringRedisTemplate.opsForValue().get("phone:code:" + username);
        Assert.isTrue(registerCode.equals(cacheCode),"验证码不正确");

        // 密码加密
        String encryptPassword = SecurityUtils.encryptPassword(password);



        // 注册用户 实际上就是向数据库中 存入数据 此处需要远程调用
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername(username);
        userInfo.setNickName(nickName);
        userInfo.setPassword(encryptPassword);
        userInfo.setPhone(username);
        R<?> registerResult = remoteUserInfoService.register(userInfo, SecurityConstants.INNER);

        // 记录日志 这里把注册日志记录在了登入日志里
        int code = registerResult.getCode();
        Assert.isTrue(code==200,"注册失败");
        sysRecordLogService.recordLogininfor(username, Constants.REGISTER, "注册成功");



    }

    public LoginUser login(LoginBody form) {
        String password = form.getPassword();
        String username = form.getUsername();
        Assert.isTrue(StringUtils.hasText(password),"密码不能为空");
        Assert.isTrue(StringUtils.hasText(username),"用户名不能为空");

        // 查询用户 远程接口

        UserInfo userInfo = remoteUserInfoService.getUserInfo(username, SecurityConstants.INNER).getData();
        Assert.notNull(userInfo,"用户不存在");

        // 校验密码 (用户输入的密码)
        // 数据库查出来的user
        LoginUser loginUser = new LoginUser();
        loginUser.setUserid(userInfo.getId());
        loginUser.setUsername(userInfo.getUsername());
        loginUser.setPassword(userInfo.getPassword());
        loginUser.setStatus(userInfo.getStatus()+"");
        sysPasswordService.validate(loginUser,password);// 密码校验

        // 更新用户（更新时间和ip) 远程接口
        UpdateUserLogin updateUserLogin =new UpdateUserLogin();
        updateUserLogin.setUserId(userInfo.getId());

        updateUserLogin.setLastLoginTime(new Date());
        updateUserLogin.setLastLoginIp(IpUtils.getIpAddr());
        R<?> updateResult = remoteUserInfoService.updateUserLogin(updateUserLogin, SecurityConstants.INNER);

        return loginUser ;
    }
}
